package cn.px.service.repair.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import cn.px.common.bean.AbstractPageResultBean;
import cn.px.common.bean.DictVO;
import cn.px.common.cache.DictCache;
import cn.px.common.exception.BusinessException;
import cn.px.common.util.BigDecimalUtil;
import cn.px.common.util.DateUtils;
import cn.px.common.util.ListUtils;
import cn.px.dao.bean.MyPage;
import cn.px.dao.dto.repair.RepairFeeDTO;
import cn.px.dao.entity.repair.RepairApplicationForm;
import cn.px.dao.entity.repair.RepairFee;
import cn.px.dao.entity.sb.SbInfo;
import cn.px.dao.entity.upms.SysFile;
import cn.px.dao.enums.SysFileTypeEnum;
import cn.px.dao.mapper.repair.RepairApplicationFormMapper;
import cn.px.dao.mapper.repair.RepairFeeMapper;
import cn.px.dao.mapper.upms.SysFileMapper;
import cn.px.dao.vo.export.repair.ExportRepairSumFeeVO;
import cn.px.dao.vo.report.RepairReportFee;
import cn.px.dao.vo.report.RepairSbInfoReportFee;
import cn.px.service.base.impl.BaseServiceImpl;
import cn.px.service.repair.RepairFeeService;
import cn.px.service.sb.SbInfoService;
import cn.px.service.util.SysFileUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description 维修费用单 service 实现类
 * @author 品讯科技
 * @date 2024-08
 * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
 */
@AllArgsConstructor
@Service("repairFeeService")
public class RepairFeeServiceImpl extends BaseServiceImpl<RepairFeeMapper, RepairFee, RepairFeeDTO> implements RepairFeeService {

    private final SysFileMapper sysFileMapper;

    private final RepairApplicationFormMapper repairApplicationFormMapper;

    private final SbInfoService sbInfoService;

    @Override
    public List<ExportRepairSumFeeVO> getSbsRepairFee(List<String> sbIds) {
        return mapper.getSbsRepairFee(sbIds);
    }

    @Override
    public int batchDelete(List<String> ids) {
        Weekend<RepairFee> weekend = new Weekend<>(RepairFee.class);
        WeekendCriteria<RepairFee, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andIn(RepairFee::getId, ids);
        mapper.deleteByExample(weekend);
        return 1;
    }

    @Override
    public AbstractPageResultBean<RepairFee> selectPageInfo(RepairFeeDTO record, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        AbstractPageResultBean<RepairFee> pageInfo = new MyPage(mapper.selectPageList(record));
        return pageInfo;
    }

    @Override
    public List<RepairFee> getModelListByDTO(RepairFeeDTO model) {
        return mapper.selectPageList(model);
    }

    @Override
    public RepairFee saveModelByDTO(RepairFeeDTO model) {
        RepairFee result = super.saveModelByDTO(model);
        model.setId(result.getId());
        this.saveFile(model);
        this.saveImage(model);
        return result;
    }

    @Override
    public void modModelByDTO(RepairFeeDTO model) {
        this.saveFile(model);
        this.saveImage(model);
        super.modModelByDTO(model);
    }

    private void saveFile(RepairFeeDTO model) {
        if (CollectionUtil.isNotEmpty(model.getFileList())) {
            Weekend<SysFile> weekend = new Weekend<>(SysFile.class);
            weekend.weekendCriteria().andEqualTo(SysFile::getType, SysFileTypeEnum.REPAIR_FEE_FILES.getValue()).andEqualTo(SysFile::getTargetId, model.getId());
            sysFileMapper.deleteByExample(weekend);
            List<SysFile> list = SysFileUtils.changeFileList(model.getFileList(), model.getId(), SysFileTypeEnum.REPAIR_FEE_FILES.getValue());
            if (CollectionUtil.isNotEmpty(list)) {
                sysFileMapper.insertListforComplex(list);
            }
        }
    }

    private void saveImage(RepairFeeDTO model) {
        if (CollectionUtil.isNotEmpty(model.getImageList())) {
            Weekend<SysFile> weekend = new Weekend<>(SysFile.class);
            weekend.weekendCriteria().andEqualTo(SysFile::getType, SysFileTypeEnum.REPAIR_FEE_IMGS.getValue()).andEqualTo(SysFile::getTargetId, model.getId());
            sysFileMapper.deleteByExample(weekend);
            List<SysFile> list = SysFileUtils.changeFileList(model.getImageList(), model.getId(), SysFileTypeEnum.REPAIR_FEE_IMGS.getValue());
            if (CollectionUtil.isNotEmpty(list)) {
                sysFileMapper.insertListforComplex(list);
            }
        }
    }

    @Override
    public RepairFee getModelById(Object id) {
        RepairFee model = mapper.selectById(id);
        Weekend<SysFile> weekendFile = new Weekend<>(SysFile.class);
        weekendFile.weekendCriteria().andEqualTo(SysFile::getTargetId, id);
        List<SysFile> sysFiles = sysFileMapper.selectByExample(weekendFile);
        List<SysFile> checkImgList = ListUtils.newArrayList();
        List<SysFile> checkFileList = ListUtils.newArrayList();
        sysFiles.forEach(item -> {
            if (item.getType().equals(SysFileTypeEnum.REPAIR_FEE_IMGS.getValue())) {
                checkImgList.add(item);
            }
            if (item.getType().equals(SysFileTypeEnum.REPAIR_FEE_FILES.getValue())) {
                checkFileList.add(item);
            }
        });
        model.setImageList(checkImgList);
        model.setFileList(checkFileList);
        RepairApplicationForm repairApplicationForm = repairApplicationFormMapper.selectById(model.getRepairId());
        if (repairApplicationForm != null) {
            model.setRepairNo(repairApplicationFormMapper.selectById(model.getRepairId()).getNo());
        }
        return model;
    }

    /**
     * 1: 如果年份是当前年份，则统计到当前月份
     * 2：如果不是当前年份，则统计全年的
     *
     * @param repairApplicationFormDTO
     * @param searchYear               查询年份
     * @return
     */
    @Override
    public List<RepairReportFee> getMonthReport(RepairFeeDTO repairApplicationFormDTO, Integer searchYear, LocalDate startMonth, LocalDate endMonth) {

        List<Map<String, LocalDateTime>> monthStartAndEndList = new ArrayList<>();
        LocalDateTime searchStartTime = null;
        LocalDateTime searchEndTime = null;
        /*if (searchYear != null) {
            LocalDate localDate = LocalDate.now();
            int year = localDate.getYear();
            // 如2021-10-15号码，则month=10，需要计算到11月份，需要加1
            int month = localDate.getMonthValue();
            if (searchYear < year) {
                month = 12;
                year = searchYear;
            }
            monthStartAndEndList = DateUtils.getMonthStartAndEndByYear(year, month);
            // 当前年份只统计到当前月，历史年份统计全年
            searchStartTime = DateUtils.getFirstDayOfThisYear(year);
            searchEndTime = DateUtils.getLastDayOfMonth(year, month);
        } else {*/
            monthStartAndEndList = DateUtils.getMonthStartAndEndByYear(startMonth, endMonth);
            searchStartTime = DateUtils.getFirstDayOfMonth(startMonth);
            searchEndTime = DateUtils.getLastDayOfMonth(endMonth);
        //}

        repairApplicationFormDTO.setSearchStartTime(searchStartTime);
        repairApplicationFormDTO.setSearchEndTime(searchEndTime);
        List<RepairFee> list = mapper.selectPageList(repairApplicationFormDTO);

        List<RepairReportFee> result = new ArrayList<RepairReportFee>();
        for (Map<String, LocalDateTime> map : monthStartAndEndList) {
            RepairReportFee vo = new RepairReportFee();
            List<RepairFee> detailList = new ArrayList<RepairFee>();
            vo.setYear(map.get("searchStartTimeMonth").getYear());
            vo.setMonth(map.get("searchStartTimeMonth").getMonthValue());
            double totalFee = 0.0;
            double meanFee = 0.0;
            int i = 0;
            for (RepairFee fee : list) {
                if ((fee.getFeeDate().compareTo(map.get("searchStartTimeMonth").toLocalDate()) >= 0) && (fee.getFeeDate().compareTo(map.get("searchEndTimeMonth").toLocalDate()) <= 0)) {
                    i++;
                    detailList.add(fee);
                    totalFee = totalFee + fee.getFee();
                }
            }
            if (totalFee == 0.0) {
                meanFee = 0.0;
            } else {
                totalFee = BigDecimalUtil.decimal(totalFee, 2);
                meanFee = BigDecimalUtil.decimal(totalFee / i, 2);
            }
            vo.setTotalFee(totalFee);
            vo.setMeanFee(meanFee);
            vo.setNum(i);
            vo.setDetailList(detailList);
            result.add(vo);
        }
        return result;
    }

    /**
     * 1: 如果年份是当前年份，则统计到当前月份
     * 2：如果不是当前年份，则统计全年的
     *
     * @param repairApplicationFormDTO
     * @param year                     查询年份
     * @return
     */
    @Override
    public List<RepairSbInfoReportFee> getSbInfoReport(RepairFeeDTO repairApplicationFormDTO, Integer year) {
        // 查询设备信息
        SbInfo sbInfo = sbInfoService.getModelById(repairApplicationFormDTO.getSbId());
        if (sbInfo == null) {
            throw new BusinessException("设备不存在，请重新选择");
        }
        if (sbInfo.getWorkYear() == null) {
            throw new BusinessException("请设置使用寿命");
        }
        if (sbInfo.getStartDate() == null) {
            throw new BusinessException("请设置设备投用日期");
        }
        Double sbWorkYear = sbInfo.getWorkYear();
        int sbStartYear = sbInfo.getStartDate().getYear();
        int startYear = sbInfo.getStartDate().getYear();
        int endYear = LocalDate.now().getYear();
        if (year != null) {
            startYear = year;
            endYear = year;
        }
        List<Map<String, LocalDateTime>> monthStartAndEndList = new ArrayList<Map<String, LocalDateTime>>();
        LocalDateTime searchStartTime = null;
        LocalDateTime searchEndTime = null;
        monthStartAndEndList = DateUtils.getYearStartAndEndByYear(startYear, endYear);
        searchStartTime = DateUtils.getFirstDayOfThisYear(startYear);
        searchEndTime = DateUtils.getLastDayOfThisYear(endYear);

        repairApplicationFormDTO.setSearchStartTime(searchStartTime);
        repairApplicationFormDTO.setSearchEndTime(searchEndTime);
        List<RepairFee> list = mapper.selectPageList(repairApplicationFormDTO);
        List<RepairSbInfoReportFee> result = new ArrayList<RepairSbInfoReportFee>();
        List<DictVO> children = DictCache.getChildren("REPAIR_FEE_TYPE");
        if (CollectionUtil.isNotEmpty(children)) {
            for (DictVO dictVO : children) {
                for (Map<String, LocalDateTime> map : monthStartAndEndList) {
                    RepairSbInfoReportFee vo = new RepairSbInfoReportFee();
                    List<RepairFee> detailList = new ArrayList<RepairFee>();
                    vo.setYear(map.get("searchStartTime").getYear());
                    double workYear = sbWorkYear - (map.get("searchStartTime").getYear() - sbStartYear);
                    double totalFee = 0.0;
                    double meanFee = 0.0;
                    int i = 0;
                    for (RepairFee fee : list) {
                        if ((fee.getFeeDate().compareTo(map.get("searchStartTime").toLocalDate()) >= 0) && (fee.getFeeDate().compareTo(map.get("searchEndTime").toLocalDate()) <= 0)) {
                            if (fee.getType() != null && dictVO.getValue().equals(fee.getType())) {
                                i++;
                                detailList.add(fee);
                                totalFee = totalFee + fee.getFee();
                            }
                        }
                    }
                    if (totalFee == 0.0) {
                    } else {
                        totalFee = BigDecimalUtil.decimal(totalFee, 2);
                    }
                    vo.setWorkYear(workYear);
                    vo.setTotalFee(totalFee);
                    vo.setNum(i);
                    vo.setType(Integer.valueOf(dictVO.getValue().toString()));
                    vo.setName(dictVO.getLabel());
                    vo.setDetailList(detailList);
                    result.add(vo);
                }
            }
        }
        return result;
    }
}
